package cc.cix.gt.org.service.impl;

import cc.cix.gt.common.entity.ResultPage;
import cc.cix.gt.common.util.SystemUtil;
import cc.cix.gt.org.dto.query.QueryRoleReq;
import cc.cix.gt.org.entity.Menu;
import cc.cix.gt.org.entity.Role;
import cc.cix.gt.org.entity.RoleMenu;
import cc.cix.gt.org.entity.UserRole;
import cc.cix.gt.org.mapper.RoleMapper;
import cc.cix.gt.org.service.IMenuService;
import cc.cix.gt.org.service.IRoleMenuService;
import cc.cix.gt.org.service.IRoleService;
import cc.cix.gt.org.service.IUserRoleService;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author cix
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role>
        implements IRoleService {

    private final IRoleMenuService roleMenuService;
    private final IUserRoleService userRoleService;
    private final IMenuService menuService;

    @Override
    public ResultPage<Role> listRole(QueryRoleReq dto) {
        IPage<Role> rolePage = lambdaQuery()
                .eq(StrUtil.isNotBlank(dto.getRoleName()), Role::getRoleName, dto.getRoleName())
                .eq(StrUtil.isNotBlank(dto.getRemark()), Role::getRemark, dto.getRemark())
                .orderByAsc(Role::getId)
                .page(new Page<>(dto.getPageNum(), dto.getPageSize()));

        rolePage.getRecords().forEach(role -> {
            List<Long> Ids = roleMenuService.lambdaQuery()
                    .eq(RoleMenu::getRoleId, role.getId())
                    .list()
                    .stream()
                    .map(RoleMenu::getMenuId)
                    .toList();

            List<Long> menuIds = new ArrayList<>();
            List<String> menuNames = new ArrayList<>();
            for (Long id : Ids) {
                Menu menu = menuService.getById(id);

                if (ObjectUtil.isNotNull(menu)) {
                    menuIds.add(menu.getId());
                    menuNames.add(menu.getMenuName());
                }
            }

            role.setMenuIds(menuIds);
            role.setMenuNames(menuNames);
        });

        return SystemUtil.getPage(rolePage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createRole(Role role) {
        save(role);

        if (!role.getMenuIds().isEmpty()) {
            setRoleMenus(role);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRoleByIds(List<String> roleIds) {
        removeByIds(roleIds);

        roleMenuService.lambdaUpdate().in(RoleMenu::getRoleId, roleIds).remove();
        userRoleService.lambdaUpdate().in(UserRole::getRoleId, roleIds).remove();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRole(Role role) {
        role.setRoleName(null);

        updateById(role);

        roleMenuService.lambdaUpdate().eq(RoleMenu::getRoleId, role.getId()).remove();
        if (!role.getMenuIds().isEmpty()) {
            setRoleMenus(role);
        }
    }

    private void setRoleMenus(Role role) {
        List<RoleMenu> roleMenus = new ArrayList<>();
        role.getMenuIds().forEach(menuId -> {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setMenuId(menuId);
            roleMenu.setRoleId(role.getId());
            roleMenus.add(roleMenu);
        });

        roleMenuService.saveBatch(roleMenus);
    }

}
